package org.dromara.common.mybatis.core.id;


import com.github.yitter.contract.IdGeneratorOptions;
import com.github.yitter.idgen.YitIdHelper;
import com.mybatisflex.core.keygen.IKeyGenerator;
import lombok.extern.slf4j.Slf4j;

import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;


@Slf4j
public class MoSiIdGenerator implements IKeyGenerator {

    public static final String MO_SI_ID = "MO_SI_ID";

    public MoSiIdGenerator() {
        this((short) getWorkerId());
    }

    public MoSiIdGenerator(short uniqueWorkerId) {
        log.info("MoSiIdGenerator >>>>>>>>>>>>> uniqueWorkerId = " + uniqueWorkerId);
        //https://gitee.com/yitter/idgenerator/tree/master/Java
        // 创建 IdGeneratorOptions 对象，可在构造函数中输入 WorkerId：
        IdGeneratorOptions options = new IdGeneratorOptions(uniqueWorkerId);
        // options.WorkerIdBitLength = 10; // 默认值6，限定 WorkerId 最大值为2^6-1，即默认最多支持64个节点。
        // options.SeqBitLength = 6; // 默认值6，限制每毫秒生成的ID个数。若生成速度超过5万个/秒，建议加大 SeqBitLength 到 10。
        // options.BaseTime = Your_Base_Time; // 如果要兼容老系统的雪花算法，此处应设置为老系统的BaseTime。
        // ...... 其它参数参考 IdGeneratorOptions 定义。

        // 保存参数（务必调用，否则参数设置不生效）：
        YitIdHelper.setIdGenerator(options);
        // 以上过程只需全局一次，且应在生成ID之前完成。
    }

    /**
     * 将MAC地址的一部分作为工作ID，并通过位操作将其限制在0到63之间
     *
     * @return
     */
    public static long getWorkerId() {
        final long WORKER_ID_BITS = 6L; // 6 bits for worker ID
        final long MAX_WORKER_ID = ~(-1L << WORKER_ID_BITS); // 范围0至63
        try {
            Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
            byte[] mac = null;
            while (networkInterfaces.hasMoreElements()) {
                NetworkInterface networkInterface = networkInterfaces.nextElement();
                if (networkInterface != null) {
                    mac = networkInterface.getHardwareAddress();
                    if (mac != null && mac.length > 0) {
                        break;
                    }
                }
            }
            if (mac == null || mac.length == 0) {
                throw new RuntimeException("Could not find network interface to generate workerId");
            }
            // Combine the last 2 bytes of MAC address and apply bit mask to limit it to 6 bits
            return ((0x000000FF & (long) mac[mac.length - 2]) | (0x0000FF00 & (((long) mac[mac.length - 1]) << 8))) & MAX_WORKER_ID;
        } catch (SocketException e) {
            throw new RuntimeException("Could not generate workerId", e);
        }
    }

    public Long nextId(Object entity) {
        return YitIdHelper.nextId();
    }

    @Override
    public Object generate(Object entity, String keyColumn) {
        return nextId(entity);
    }
}

